package ee.ut.math.chess.game.controller;

import java.io.IOException;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ee.ut.math.chess.base.model.Move;
import ee.ut.math.chess.base.model.exception.GameLogicException;
import ee.ut.math.chess.game.manager.GameManager;
import ee.ut.math.chess.game.model.Game;

public class GameServlet extends HttpServlet{
	
	private static final String GAME_OVER = "GameOver";
	private static final long serialVersionUID = 1L;
	private static final String NEW_GAME = "newGame";
	private static final String MOVE = "move";
	private static final String PING = "ping";

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String actionId = req.getParameter("action");
		String gameId = req.getParameter("gameId");
		String depthLevel = req.getParameter("depth");
		if (NEW_GAME.equals(actionId)) {
			handleNewGameRequest(resp,depthLevel);
			return;
		}

		Game game = getGame(resp, gameId);
		if (game == null) {
			return;
		}
		if (PING.equals(actionId)) {
			Long lastUpdate = Long.valueOf(req.getParameter("lastMoveTimestamp"));
			handlePingRequest(lastUpdate, game, resp);
		}
		else if (MOVE.equals(actionId)) {
			String moveString = req.getParameter(MOVE);
			handleMoveRequest(moveString, game, resp);			
		}
		
		if (game.hasEnded()) {
			GameManager.removeGame(game.getId());
		}
	}
	
	/*
	///////////////////////private methods
	*/
	private void handleNewGameRequest(HttpServletResponse resp, String depth) throws IOException {
		Game game = GameManager.newGame();
		game.setDepth(Integer.parseInt(depth));
		
		String json = wrapAdditionalInfoToGameJSON(game.toJSON(), null);
		resp.getWriter().print(json);
	}
	
	private Game getGame(HttpServletResponse resp, String gameId) {
		if (gameId == null) {
			resp.setStatus(600);//no gameId
			return null;
		}
		
		Game game = GameManager.getGame(UUID.fromString(gameId));
		if (game == null) {
			resp.setStatus(601);//no game 
			return null;
		}
		return game;
	}
	
	private void handleMoveRequest(String moveString, Game game, HttpServletResponse resp) throws IOException {
		String json = null;
		try {
			game.move(new Move(moveString));
			String additionalInfo = null;
			if (game.hasEnded()) {
				additionalInfo = GAME_OVER;
			}
			json = wrapAdditionalInfoToGameJSON(game.toJSON(), additionalInfo);
		} catch (GameLogicException e) {
			json = wrapAdditionalInfoToGameJSON(game.toJSON(), e.getClass().getSimpleName());
			
		}
		
		resp.getWriter().print(json);
	}
	
	private void handlePingRequest(Long clientLastUpdated, Game game, HttpServletResponse resp) throws IOException {
		if (clientLastUpdated != game.getLastMoveTimestamp()) {
			String additionalInfo = null;
			if (game.hasEnded()) {
				additionalInfo = GAME_OVER;
			}
			resp.getWriter().print(wrapAdditionalInfoToGameJSON(game.toJSON(), additionalInfo));
			return;
		}
		
	}
	
	private String wrapAdditionalInfoToGameJSON(String gameInfo, String additionalInfo) {
		return "{\"gameInfo\": " + gameInfo + ",\n\"additionalInfo\":\n\"" + additionalInfo + "\"}";
	}
}

